class: center, middle, inverse, title-slide .title[ # {detourr} ] .subtitle[ ## Interactive and performant tour visuals for the web ] .author[ ### Casper Hart ] .date[ ### 2022-03-25 ] --- # Tours in R The `{tourr}` package has a comprehensive set of tour path generators and display methods, with some limitations: - Portability - Interactivity - Performance - Extensibility To address these limitations, we take a _detour_ in to web technologies... --- # ... and we want to avoid this <img src="data:image/png;base64,#tour_html.gif" width="100%" /> --- .center[ <img src="data:image/png;base64,#detourr_logo.png" height="400" /> .strong[ AHEAD ] .strong[ FOLLOW <img src="data:image/png;base64,#right_arrow.png" height="30" /> <img src="data:image/png;base64,#github_logo.png" height="30" /> <img src="data:image/png;base64,#twit.svg" height="30" /> @casperhart ] ] --- # Introducing `{detourr}`
--- # Portability `{detourr}` visuals are written in TypeScript / JavaScript, using `{HTMLWidgets}` to work with R. It runs well with: - Any browser - The RStudio viewer - VScode webview - Knitr (with html output) - Shiny - `{xaringan}` slides --- # Interactivity .pull-left[ .big[ - Orbit Controls - Selection and Brushing - Timeline - Labels ] ] .pull-right[
] --- # Linked selection with `{crosstalk}`
--- # Linked selection with `{crosstalk}` Compatible with: - `plotly/plotly.R` - `rstudio/leaflet` - `rstudio/DT` --- # User API {detourr} has a declarative API for building a tour visual. Instantiate a `detour` object with `detour()`: .panelset[ .panel[.panel-name[R Code] ```r remotes::install_github("casperhart/detour@v0.0.2") ``` ```r *detour( olive, tour_aes( projection = palmitic:eicosenoic, colour = region ) ) ``` ] .panel[.panel-name[Output] ``` #> # A tibble: 0 × 2 #> # … with 2 variables: is_new_basis <lgl>, projection_matrix <list> ``` ] ] --- # User API: tour path .panelset[ .panel[.panel-name[R Code] ```r detour( olive, tour_aes(projection = palmitic:eicosenoic, colour = region) *) |> tour_path(grand_tour(3)) ``` ] .panel[.panel-name[Output] ``` #> # A tibble: 539 × 2 #> is_new_basis projection_matrix #> <lgl> <list> #> 1 TRUE <dbl [8 × 3]> #> 2 FALSE <dbl [8 × 3]> #> 3 FALSE <dbl [8 × 3]> #> 4 FALSE <dbl [8 × 3]> #> 5 FALSE <dbl [8 × 3]> #> 6 FALSE <dbl [8 × 3]> #> 7 FALSE <dbl [8 × 3]> #> 8 FALSE <dbl [8 × 3]> #> 9 FALSE <dbl [8 × 3]> #> 10 FALSE <dbl [8 × 3]> #> # … with 529 more rows ``` ] ] --- # User API: display methods .panelset[ .panel[.panel-name[R Code] ```r detour( olive, tour_aes(projection = palmitic:eicosenoic, colour = region) ) |> tour_path(grand_tour(3)) |> * show_scatter() ``` ] .panel[.panel-name[Output]
] ] --- # Displays: `show_scatter()`
--- # Displays: `show_sage()`
--- # Displays: `show_slice()`
--- # Performance: scripting Javascript is... pretty quick! <img src="data:image/png;base64,#chrome_speed.png" width="800"/><img src="data:image/png;base64,#v8.svg" width="150" height="150" /> --- # Performance: matrix operations Vanilla JavaScript is not ideal for matrix operations... -- but **TensorFlow.js** is. -- Backend options: - CPU -- - WebAssembly (WASM) -- - WASM + SIMD -- - WASM + SIMD + threads -- - WebGL / GPU Acceleration? --- # Performance: rendering .pull-left[ - SVG - HTML5 Canvas + 2D - HTML5 Canvas + WebGL WebGL rendering is used for `scatter`, `slice`, and `sage` displays via `Three.JS` New displays can use any of these. ] .pull-right[ <img src="data:image/png;base64,#rick-bobby-will-ferrell.gif" width="500" /> <img src="data:image/png;base64,#html5.svg" height="100" /> <img src="data:image/png;base64,#webgl.svg" height="100" /> <img src="data:image/png;base64,#three.svg" height="100" /> ] --- # Extensibility - Written in **TypeScript** -- - Existing widgets can be **extended** through inheritance -- - Controls and timeline are **reusable** -- - `webpack-dev-server` for hot reloading during development -- - **Independent** widgets for each display method. -- - Tour paths compatible with `{tourr}` --- .center2[ <img src="data:image/png;base64,#thanks.gif" /> ]